C************************************************************************
C
C  FISHTANK.FOR -- This program demonstrates multi-object non-destructive
C  animation. The coral background is displayed on page 2 and copied to
C  page 0, the visual page. A packed pixel run file containing the 6 fish
C  is displayed on page 1, and then FG_GETIMAGE is used to load the fish
C  into the fish bitmaps.
C
C  To make the fish move, the background is copied to page 1 and the fish
C  are put over the background using FG_CLPIMAGE and FG_FLPIMAGE. The
C  fish are clipped at the edge of the screen. Page 1 is then copied to
C  page 0 using FG_COPYPAGE. This process is then repeated in a loop.
C
C  To compile this program and link it with Fastgraph 4.0:
C
C     FL /FPi /4I2 /4Nt /AM FISHTANK.FOR /link FGM   (MS FORTRAN 4.x/5.x)
C     FL32 FISHTANK.FOR FG32MSF.LIB                  (FORTRAN PowerStation)
C
C  This program also can be linked with Fastgraph/Light 4.0 (real mode
C  only) if you replace the FGM library reference with FGLM.
C
C  For more examples of animation using Fastgraph, or for an evaluation
C  copy of Fastgraph/Light, call DDBBS at (702) 796-7134. For Fastgraph
C  voice support, call Ted Gruber Software at (702) 735-1980.
C
C************************************************************************

$INCLUDE: 'C:\FG\FASTGRAF.FI'

      PROGRAM MAIN
      IMPLICIT INTEGER (A-Z)

      COMMON /SEED/ SEED

C *** fish bitmaps ***

      INTEGER*1 FISHES
      COMMON /MAPS/ FISHES(5356), OFFSET(6)

C *** palette values

      INTEGER COLORS(16)
      DATA COLORS /0,1,2,3,4,5,6,7,16,0,18,19,20,21,22,23/

C *** in case we're compiling for protected mode

      CALL FG_INITPM

C *** make sure the system supports video mode 13 with 4 pages

      IF (FG_TESTMODE(13,4) .EQ. 0) THEN
         WRITE(6,*)
         WRITE(6,*) 'This program requires an EGA or VGA card'
         WRITE(6,*) 'with at least 128k. If an EGA card is'
         WRITE(6,*) 'present, it must be the active adapter.'
         STOP ' '
      END IF

C *** initialize the video environment

      OLD_MODE = FG_GETMODE()
      CALL FG_SETMODE(13)
      CALL FG_PALETTES(COLORS)
      CALL RANDOMIZE

C *** get the coral background from a file and put it on page 2

      CALL FG_SETPAGE(2)
      CALL FG_MOVE(0,199)
      STATUS = FG_SHOWPPR('CORAL.PPR'//CHAR(0),320)

C *** copy the background from page 2 to page 0, the visual page

      CALL FG_COPYPAGE(2,0)

C *** get the fish

      CALL GET_FISH

C *** make the fish go

      CALL GO_FISH

C *** restore the original video state

      CALL FG_SETMODE(OLD_MODE)
      CALL FG_RESET

      STOP ' '
      END

C************************************************************************
C*                                                                      *
C*            get_fish -- fill up the fish bitmap arrays                *
C*                                                                      *
C************************************************************************

      SUBROUTINE GET_FISH
      IMPLICIT INTEGER (A-Z)

      INTEGER*1 FISHES
      COMMON /MAPS/ FISHES(5356), OFFSET(6)
      COMMON /SIZE/ FISH_X1(6), FISH_Y1(6), WIDTH(6), HEIGHT(6)

C *** get the fish from a file and put them on page 1

      CALL FG_SETPAGE(1)
      CALL FG_MOVE(0,199)
      STATUS = FG_SHOWPPR('FISH.PPR'//CHAR(0),320)

C *** build the fish bitmaps

      I = 1
      DO 10 FISH_NUM = 1,6
         CALL FG_MOVE(FISH_X1(FISH_NUM),FISH_Y1(FISH_NUM))
         CALL FG_GETIMAGE(FISHES(I),WIDTH(FISH_NUM),HEIGHT(FISH_NUM))
         OFFSET(FISH_NUM) = I
         I = I + WIDTH(FISH_NUM) * HEIGHT(FISH_NUM)
10    CONTINUE

      RETURN
      END

C************************************************************************
C*                                                                      *
C*             go_fish -- make the fish swim around                     *
C*                                                                      *
C************************************************************************

      SUBROUTINE GO_FISH
      IMPLICIT INTEGER (A-Z)

C     There are 11 fish total, and 6 different kinds of fish. These
C     arrays keep track of what kind of fish each fish is, and how each
C     fish moves:
C
C     fish()   -- which fish bitmap applies to this fish?
C     x()      -- starting x coordinate
C     y()      -- starting y coordinate
C
C     xmin()   -- how far left (off screen) the fish can go
C     xmax()   -- how far right (off screen) the fish can go
C     xinc()   -- how fast the fish goes left and right
C     dir()    -- starting direction for each fish
C
C     ymin()   -- how far up this fish can go
C     ymax()   -- how far down this fish can go
C     yinc()   -- how fast the fish moves up or down
C     yturn()  -- how long fish can go in the vertical direction
C               before stopping or turning around
C     ycount() -- counter to compare to yturn

      PARAMETER (NFISH = 11)

      INTEGER*1 KEY, AUX

      INTEGER*1 FISHES
      COMMON /MAPS/ FISHES(5356), OFFSET(6)

      INTEGER FISH(NFISH), X(NFISH), Y(NFISH)
      INTEGER XMIN(NFISH), XMAX(NFISH), XINC(NFISH)
      INTEGER YMIN(NFISH), YMAX(NFISH), YINC(NFISH)
      INTEGER DIR(NFISH), YTURN(NFISH), YCOUNT(NFISH)

      DATA FISH /   2,   2,   3,   4,   4,   1,   1,   6,   5,   3,   4/
      DATA X    /-100,-150,-450,-140,-200, 520, 620,-800, 800, 800,-300/
      DATA Y    /  40,  60, 150,  80,  70, 190, 180, 100,  30, 130,  92/

      DATA XMIN /-300,-300,-800,-200,-200,-200,-300,-900,-900,-900,-400/
      DATA XMAX / 600, 600,1100,1000,1000, 750, 800,1200,1400,1200, 900/
      DATA XINC /   2,   2,   8,   5,   5,  -3,  -3,   7,  -8,  -9,   6/
      DATA DIR  /   0,   0,   0,   0,   0,   1,   1,   0,   1,   1,   0/

      DATA YMIN /  40,  60, 120,  70,  60, 160, 160,  80,  30, 110,  72/
      DATA YMAX /  80, 100, 170, 110, 100, 199, 199, 120,  70, 150, 122/
      DATA YTURN/  50,  30,  10,  30,  20,  10,  10,  10,  30,   20, 10/
      DATA YCOUNT/  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0/
      DATA YINC /   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0/

C *** make the fish swim around

10    CONTINUE

C *** copy the background from page 2 to page 1

      CALL FG_COPYPAGE(2,1)

C *** put all the fish on the background

      DO 20 I = 1,11

         CALL FG_SETPAGE(1)
         YCOUNT(I) = YCOUNT(I) + 1
         IF (YCOUNT(I) .GT. YTURN(I)) THEN
            YCOUNT(I) = 0
            YINC(I) = IRANDOM(-1,1)
         END IF
         Y(I) = Y(I) + YINC(I)
         Y(I) = MIN(YMAX(I),MAX(Y(I),YMIN(I)))

         IF (X(I) .GE. 0 .AND. X(I) .LT. 320) THEN
            CALL PUT_FISH(FISH(I),X(I),Y(I),DIR(I))
         ELSE IF (X(I) .LT. 0 .AND. X(I) .GT. -72) THEN
            CALL FG_TRANSFER(0,71,0,199,104,199,1,3)
            CALL FG_SETPAGE(3)
            CALL PUT_FISH(FISH(I),X(I)+104,Y(I),DIR(I))
            CALL FG_TRANSFER(104,175,0,199,0,199,3,1)
         END IF
         X(I) = X(I) + XINC(I)
         IF (X(I) .LE. XMIN(I) .OR. X(I) .GE. XMAX(I)) THEN
            XINC(I) = -XINC(I)
            DIR(I) = 1 - DIR(I)
         END IF

20    CONTINUE

C *** copy page 1 to page 0

      CALL FG_SETPAGE(0)
      CALL FG_COPYPAGE(1,0)

C *** intercept a keystroke, if it is escape exit the program

      CALL FG_INTKEY(KEY,AUX)
      IF (KEY .NE. 27) GO TO 10

      RETURN
      END

C************************************************************************
C*                                                                      *
C*                irandom -- random number generator                    *
C*                                                                      *
C************************************************************************

      FUNCTION IRANDOM(MIN,MAX)
      IMPLICIT INTEGER (A-Z)

      TEMP = IEOR(SEED,ISHFT(SEED,-7))
      SEED = IAND(IEOR(ISHFT(TEMP,8),TEMP),#7FFF)
      IRANDOM = MOD(SEED,MAX-MIN+1) + MIN

      RETURN
      END

C************************************************************************
C*                                                                      *
C*      put_fish -- draw one of the six fish anywhere you want          *
C*                                                                      *
C************************************************************************

      SUBROUTINE PUT_FISH(FISH_NUM,X,Y,FISH_DIR)
      IMPLICIT INTEGER (A-Z)

      INTEGER*1 FISHES
      COMMON /MAPS/ FISHES(5356), OFFSET(6)
      COMMON /SIZE/ FISH_X1(6), FISH_Y1(6), WIDTH(6), HEIGHT(6)

C *** move to position where the fish will appear

      CALL FG_MOVE(X,Y)

C *** draw a left- or right-facing fish, depending on fish_dir

      I = OFFSET(FISH_NUM)
      IF (FISH_DIR .EQ. 0) THEN
         CALL FG_FLPIMAGE(FISHES(I),WIDTH(FISH_NUM),HEIGHT(FISH_NUM))
      ELSE
         CALL FG_CLPIMAGE(FISHES(I),WIDTH(FISH_NUM),HEIGHT(FISH_NUM))
      END IF

      RETURN
      END

C************************************************************************
C*                                                                      *
C*       randomize -- get a seed for the random number generator        *
C*                                                                      *
C************************************************************************

      SUBROUTINE RANDOMIZE
      IMPLICIT INTEGER (A-Z)

      COMMON /SEED/ SEED

      INTEGER*4 FG_GETCLOCK

      SEED = IAND(INT(FG_GETCLOCK()),#7FFF)

      RETURN
      END

C************************************************************************
C*                                                                      *
C*      block data -- initialize arrays in common blocks                *
C*                                                                      *
C************************************************************************

      BLOCK DATA
      IMPLICIT INTEGER (A-Z)

      COMMON /SIZE/ FISH_X1(6), FISH_Y1(6), WIDTH(6), HEIGHT(6)
      DATA FISH_X1 /  0, 64,128,200,  0, 80/
      DATA FISH_Y1 /199,199,199,199,150,150/
      DATA WIDTH   / 28, 27, 34, 28, 31, 34/
      DATA HEIGHT  / 25, 38, 26, 30, 22, 36/

      END
